<?php
/**
 * BaseSpider.php class file.
 * @author wudg <544038230@qq.com>
 * @date 2020/10/23- 9:51 上午
 */

namespace common\drivers\spiderProduct;

use common\constants\PlatformConst;
use common\drivers\CookieDriver;
use common\exception\DriverException;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Exception\ConnectException;

use Yii;
use GuzzleHttp\Cookie\CookieJar;

class BaseSpider
{


    /**
     * cookies 设置
     * @var array
     */
    protected $cookies = [];


    /**
     * 频率过快重复次数
     * @var int
     */
    protected $tryTimes = 3;

    /**
     * 重试等待秒数
     * @var int
     */
    protected $waitTimes = 1;

    /**
     * 头信息设置
     * @var array
     */
    protected $headers = [];

    /**
     * 错误信息
     * @var
     */
    protected $errorInfo = [];


    /**
     * 万邦接口key
     * @var string
     */
    protected $key = 'tel13655514903';


    /**
     * 万邦接口秘钥
     * @var string
     */
    protected $secret = '20201227';

    /**
     * 获取的采集资源信息
     * @var
     */
    protected $resources;


    /**
     * 商品字段格式
     * @var array
     */
    protected $productInfo = [
        'title' => '', //商品标题信息
        'skus' => [], //sku属性信息
        'video' => '', //视频地址
        'prices' => 0, //价格
        'num_iid' => '', //商品主键
        'platform' => '', //平台
        'cid' => 0, //商品类目id
        'attr' => [], //属性信息
        'main_pic' => '', //封面图
        'sku_img' => [],//sku 图
        'mall_id' => 0, //所属店铺id
        'mall_name' => '', //所属店铺名称
        'pics' => [], //主图信息
        'pc_desc' => '', //电脑端详细
        'detail_gallery' => '', //描叙详情图
        'goods_desc' => '', //商品详情，纯文本
        'm_desc' => '', //移动端详细
        'extend_data' => [], //扩展信息
    ];

    public function __construct($cookies = [], $headers = [])
    {
        $cookies && $this->cookies = $cookies;
        $headers && $this->headers = $headers;
    }


    /**
     * 设置字符串字符集
     * @param $str
     * @return string
     */
    public function Utf8String($str)
    {
        $encode = mb_detect_encoding($str, ["ASCII", 'UTF-8', "GB2312", "GBK", 'BIG5']);
        if (strtoupper($encode) != 'UTF-8') $str = mb_convert_encoding($str, 'utf-8', $encode);
        return $str;
    }

    /**
     * 提示类错误信息
     */
    public function setNoticeError()
    {
        $columns = [
            'mall_name' => '店铺名称',
            'pics' => '轮播图',
            'pc_desc' => '电脑端详情',
            'attr' => '属性',
            'cid' => '商品分类',
            'main_pic' => '商品主图'
        ];
        foreach ($columns as $column => $name) {
            if (!$this->productInfo[$column]) {
                $this->errorInfo[$column] = $name . "获取失败";
            }
        }
    }

    /**
     * 检测远程文件是否存在
     * @param string $url
     * @return bool
     */
    public function _img_exists($url = '')
    {
        ini_set("max_execution_time", 0);
        $str = @file_get_contents($url, 0, null, 0, 1);
        if (strlen($str) <= 0) return false;
        return $str ? true : false;
    }

    /**
     * 抓取采集页面内容
     * @param string $url
     * @param array $params
     * @param array $headers
     * @param array $cookie
     * @return \Psr\Http\Message\ResponseInterface|false
     */
    protected function spiderContent(string $url, array $params = [], array $headers = [], array $cookie = [])
    {
        $tryTimes = 0;
        while ($tryTimes < $this->tryTimes)
        {
            try {
                $domain = parse_url($url)['host'];
                $cookieJar = CookieJar::fromArray(count($cookie) ? $cookie : $this->cookies, $domain);
                $client = new Client([
                    //根域名
                    'cookies' => $cookieJar,
                    'headers' => count($headers) ? $headers : $this->headers,
                    'verify' => false
                ]);
                $response = $client->get($url, $params);
//        $content = $response->getBody()->getContents();
//        $headers = $response->getHeaders();
                $status = $response->getStatusCode();
                if ($status != 200) {
                    $this->errorInfo['spider_error_code'] = $status;
                    return false;
//            throw new DriverException('请求异常');
                }

                return $response;
            } catch (GuzzleException $e) {
                $tryTimes++;
                sleep($this->waitTimes);
                continue;
            }catch (RequestException $e) {
                $tryTimes++;
                sleep($this->waitTimes);
                continue;
            }catch (ConnectException $e) {
                $tryTimes++;
                sleep($this->waitTimes);
                continue;
            }
        }


    }

    protected function spiderContentCurl(string $url, array $params = [], array $headers = [], array $cookie = [])
    {
        if (!$url) return '';
        if ($params) {
            $url .= '?' . http_build_query($params);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
        if (stripos($url, "https://") !== FALSE) {
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);  // 从证书中检查SSL加密算法是否存在
        }
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['user-agent:' . 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36']);
        if (isset($headers['referer'])) {
            curl_setopt($ch, CURLOPT_REFERER, $headers['referer']);
        }
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, Yii::$app->params['request_timeout']);
        if ($this->cookies) {
            $cookies = [];
            foreach ($this->cookies as $name => $value) {
                $cookies[] = $name . "=" . $value;
            }
            curl_setopt($ch, CURLOPT_COOKIE, implode(";", $cookies));
        }
        $response = curl_exec($ch);
        if ($error = curl_error($ch)) {
            $this->errorInfo['getContentsError'] = '抓取内容页面错误，http状态码:' . $error;
            return false;
        }
        curl_close($ch);
        return $this->Utf8String($response);
    }
}